import xmlrpc.client as  xmlrpclib

from django.conf import settings

from supervisor_dj.models import Supervisor_Process, SupervisorHost

SUPERVISOR_PASS = getattr(settings, 'SUPERVISOR_PASS', None)
SUPERVISOR_USER = getattr(settings, 'SUPERVISOR_USER', None)


class Supervisor_Process_Managet_Class:
    msg_res = {"status_code": True, "msg": None}

    def __init__(self, username=None, password=None, ip=None, port=None):
        self.username = username if username else SUPERVISOR_USER
        self.password = password if password else SUPERVISOR_PASS
        self.ip = ip
        self.port = port if port else 9001

    def get_connecti(self, ip=None, port=None, ):
        """
        :param ip:
        :param port:
        :param username:
        :param password:
        :return:  返回连接对象     server = xmlrpclib.Server('http://zrd:sh123!@192.168.1.60:9001/RPC2/')
        """

        if self.username and self.password:
            # 有密码和账号
            connection_info = f'http://{self.username}:{self.password}@{ip}:{port}/RPC2/'
            server = xmlrpclib.Server(connection_info).supervisor
            return server

        # 无密码和账号
        connection_info_no_pass = f'http://{ip}:{port}/RPC2/'
        return xmlrpclib.Server(connection_info_no_pass).supervisor

    def start_or_stop(self, process_name=None, ip=None, action=None, ):
        qs = Supervisor_Process.objects.filter(name=process_name, ip=ip)
        if not qs.exists():
            self.msg_res['status_code'] = False
            self.msg_res['msg'] = f'{process_name}-{ip}不存在'
            return self.msg_res
        qs = qs.first()
        supervisor_host = qs.supervisor_host

        try:
            # 获取连接对象
            super_obj = self.get_connecti(ip=qs.ip, port=qs.supervisor_host.port)

            if action == 'start':
                # 启动进程
                super_obj.startProcess(process_name)
            elif action == 'stop':
                # 停止进程
                super_obj.stopProcess(process_name)
            else:
                self.msg_res['status_code'] = False
                self.msg_res['msg'] = f'没有{action}方法'
                return self.msg_res

            res_detail = super_obj.getProcessInfo(process_name)
            # 清空原有信息
            qs.delete()
            # TODO 后台队列写入
            data = Supervisor_Process.objects.create(
                name=process_name, ip=ip,
                detail=res_detail if res_detail else {},
                supervisor_host=supervisor_host)
            self.msg_res['status_code'] = True
            self.msg_res['msg'] = f'{process_name} {ip} {action}成功'
            # self.msg_res['data'] = data
            return self.msg_res
        except xmlrpclib.Fault  as e:
            self.msg_res['status_code'] = False
            self.msg_res['msg'] = e.faultString
            return self.msg_res
        except Exception as e:
            self.msg_res['status_code'] = False
            self.msg_res['msg'] = e
            return self.msg_res

    def restart(self, process_name=None, ip=None, ):
        qs = Supervisor_Process.objects.filter(name=process_name, ip=ip)
        # 查询对象是否存在
        if not qs.exists():
            self.msg_res['status_code'] = False
            self.msg_res['msg'] = f'{process_name}-{ip}不存在'
            return self.msg_res
        qs = qs.first()
        supervisor_host = qs.supervisor_host

        # 获取连接对象
        super_obj = self.get_connecti(ip=qs.ip, port=qs.supervisor_host.port)
        try:
            # 停止进程
            super_obj.stopProcess(process_name)
        except xmlrpclib.Fault as e:
            # 停止失败, 不需要返回值
            print(process_name + e.faultString)
        except Exception as e:
            # 停止失败 ，不需要返回值
            print(e)

        try:
            # 启动进程
            super_obj.startProcess(process_name)
        except xmlrpclib.Fault as e:
            self.msg_res['status_code'] = False
            self.msg_res['msg'] = e.faultString
            return self.msg_res
        except Exception as e:
            self.msg_res['status_code'] = False
            self.msg_res['msg'] = e
            return self.msg_res

        # TODO 后台队列写入 --- start -----
        res_detail = super_obj.getProcessInfo(process_name)
        # 清空原有信息
        qs.delete()

        Supervisor_Process.objects.create(
            name=process_name, ip=ip,
            detail=res_detail if res_detail else {},
            supervisor_host=supervisor_host)
        # TODO 后台队列写入 --- end -----
        self.msg_res['status_code'] = True
        self.msg_res['msg'] = f'{process_name} {ip} 重启成功'
        # self.msg_res['data'] = data
        return self.msg_res

    def get_processes_from_host(self, ip=None, port=None):
        """
        从主机上获取所有进程信息
        :param ip:
        :return: [{process2_dict_obj}, {process2_dict_obj},....]
        """
        ip = ip if ip else self.ip
        if not ip:
            self.msg_res['status_code'] = False
            self.msg_res['msg'] = '必须传入ip'
            return self.msg_res

        super_obj = self.get_connecti(ip=ip, port=self.port, )
        qs = Supervisor_Process.objects.filter(ip=ip)
        host = None
        if qs.exists():
            host = qs.first().supervisor_host
            qs.delete()
        try:
            processes_obj = super_obj.getAllProcessInfo()
            tmp = []
            for process_ in processes_obj:
                process_name = process_['name']
                s = Supervisor_Process(name=process_name, ip=ip, detail=process_, supervisor_host=host)
                tmp.append(s)
            Supervisor_Process.objects.bulk_create(tmp)
            self.msg_res['status_code'] = True
            self.msg_res['msg'] = f"{ip}刷新进程信息成功"
            return self.msg_res

        except xmlrpclib.Fault as e:
            self.msg_res['status_code'] = False
            self.msg_res['msg'] = e.faultString
            return self.msg_res
        except Exception as e:
            self.msg_res['status_code'] = False
            self.msg_res['msg'] = e
            return self.msg_res

    def refresh_allhost_allprocess(self):
        """
        刷新所有主机所有进程
        :return:
        """
        all_host = SupervisorHost.objects.all()
        Supervisor_Process.objects.all().delete()
        bulk_insert_to_db = []
        try:
            for host in all_host:
                host_ip = host.ip
                host_port = host.port
                super_obj = self.get_connecti(ip=host_ip, port=host_port, )
                process_list = super_obj.getAllProcessInfo()
                # process_list = Supervisor_Process(ip=host_ip, detail=processes_obj, supervisor_host=host)
                for process in process_list:
                    tmp = Supervisor_Process(ip=host_ip, name=process['name'], detail=process, supervisor_host=host)
                    bulk_insert_to_db.append(tmp)
                self.msg_res['status_code'] = True
                self.msg_res['msg'] = f"刷新所有进程信息成功"
            Supervisor_Process.objects.bulk_create(bulk_insert_to_db,batch_size=100)
            return self.msg_res
        except xmlrpclib.Fault as e:
            self.msg_res['status_code'] = False
            self.msg_res['msg'] = e.faultString
            return self.msg_res


    def get_a_process_info_from_host(self, ip=None, port=None, process_name=None):
        """
        从主机上获取一个进程信息
        :param ip:
        :param port:
        :param process_name:
        :return:
        """
        ip = ip
        if not ip or not process_name:
            # msg_res = {"status_code": None, "msg": None}
            self.msg_res['status_code'] = False
            self.msg_res['msg'] = '必须传入ip process_name'
            return self.msg_res

        super_obj = self.get_connecti(ip=ip, port=self.port, )
        try:
            process_obj = super_obj.getProcessInfo(process_name)
            return process_obj
        except xmlrpclib.Fault as e:
            self.msg_res['status_code'] = False
            self.msg_res['msg'] = e.faultString
            return self.msg_res
        except Exception as e:
            self.msg_res['status_code'] = False
            self.msg_res['msg'] = e
            return self.msg_res



"""
进程管理类需实现功能
    连接
    获取
        所有进程信息(一台主机上所有进程) 
        单个进程信息
    动作
        启动,停止,重启
    存储
        单个进程刷新入库
        所有进程刷新入库
        启动,停止,重启等动作刷新入库
"""

"""
进程管理model(表)


主机:
    主机名
"""